using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.MultiTenancy;
using Abp.Runtime.Security;
using Abp.UI;
using Yozeev.Authentication.External;
using Yozeev.Authentication.JwtBearer;
using Yozeev.Authorization;
using Yozeev.Models.TokenAuth;
using Yozeev.MultiTenancy;
using Yozeev.UserManagerment.Users;
using Abp.Runtime.Caching;
using Yozeev.Authorization.Impersonation;
using Abp;
using Abp.Domain.Uow;
using Abp.IdentityFramework;
using Abp.Json;
using L._52ABP.Common.Consts;
using Yozeev.Authentication.External.ExternalAuth;
using Yozeev.Authentication.External.ExternalAuth.Dto;
using Yozeev.DataFileObjects;
using Yozeev.DataFileObjects.DataTempCache;
using Yozeev.Security.Captcha;
using Yozeev.UserManagerment.Users.UserLink;
using Abp.Extensions;
using L._52ABP.Common.Net.MimeTypes;
using L._52ABP.Core.VerificationCodeStore;
using Yozeev.BusinessLogic.DomainService;
using Yozeev.Models;
using Yozeev.BusinessLogic;
using Yozeev.EntityFrameworkCore;
using Yozeev.SystemConfig.BasicConfig.DomainService;
using Yozeev.BusinessLogic.Stats.Dtos;
using Abp.Domain.Entities.Auditing;
using Microsoft.Extensions.Configuration;
using Yozeev.WechatManagement.WechatAppConfigs;
using Yozeev.WechatManagement.WechatAppConfigs.DomainService;
using Senparc.Weixin.MP.Entities;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.WxOpen.AdvancedAPIs.Sns;
using Senparc.CO2NET.HttpUtility;
using Abp.Web.Models;
using Yozeev.Help;
using Senparc.Weixin.TenPay;
using System.Text;
using Yozeev.Authorization.Roles;
using Senparc.Weixin.MP.Helpers;
using Microsoft.AspNetCore.Http;
using Senparc.Weixin.MP;
using Senparc.Weixin.TenPay.V3;
using DotNetCore.CAP;
using Microsoft.AspNetCore.Hosting;
using Yozeev.Configuration;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Yozeev.Models.Ticket;
using Yozeev.Models.Wechat;
using System.Collections;
using Yozeev.Common;

namespace Yozeev.Controllers
{
    [Route("api/[controller]/[action]")]
    public class WechatPayController : CommonController//YozeevControllerBase
    {
        private readonly ITenantCache _tenantCache;
        private readonly ICacheManager _cacheManager;
        private readonly IImpersonationManager _impersonationManager;
        private readonly IUserLinkManager _userLinkManager;
        private readonly IdentityOptions _identityOptions;
        private readonly IDataTempFileCacheManager _dataTempFileCacheManager;
        private readonly IDataFileObjectManager _dataFileObjectManager;
        private readonly ActivityManager _activityManager;
        //private readonly SourceManager _sourceManager;
        public readonly TicketDetailManager _ticketDetailManager;
        private readonly IConfigurationRoot _appConfiguration;
        private readonly WechatAppConfigManager _wechatAppConfigManager;
        private readonly ActivityTempManager _activityTempManager;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ICapPublisher _capBus;


        public WechatPayController(
            ITenantCache tenantCache,
            ICacheManager cacheManager,
            IImpersonationManager impersonationManager,
            IUserLinkManager userLinkManager,
            IOptions<IdentityOptions> identityOptions,
            UserManager userManager, 
            IDataFileObjectManager dataFileObjectManager, 
            IDataTempFileCacheManager dataTempFileCacheManager
            , ActivityManager activityManager
            , SourceManager sourceManager
            , ScheduleManager scheduleManager
            , PayMethodManager payMethodManager
            , TicketPriceManager ticketPriceManager
            , CustomerManager customerManager
            , TicketDetailManager ticketDetailManager
            , WechatAppConfigManager wechatAppConfigManager
            , ActivityTempManager activityTempManager
            , IHttpContextAccessor httpContextAccessor
            , ICapPublisher capBus
            , IHostingEnvironment env
            , TravelAgencyManager travelManager
            ) :base(sourceManager, scheduleManager, payMethodManager, cacheManager, ticketPriceManager, customerManager, userManager, travelManager)
        {
            _tenantCache = tenantCache;
            _cacheManager = cacheManager;
            _impersonationManager = impersonationManager;
            _userLinkManager = userLinkManager;
            _identityOptions = identityOptions.Value;
            _dataFileObjectManager = dataFileObjectManager;
            _dataTempFileCacheManager = dataTempFileCacheManager;
            _activityManager = activityManager;
            _ticketDetailManager = ticketDetailManager;
            _wechatAppConfigManager = wechatAppConfigManager;
            _activityTempManager = activityTempManager;
            _httpContextAccessor = httpContextAccessor;
            _capBus = capBus;

            //读取配置文件appsettings.json
            //string path = System.IO.Directory.GetCurrentDirectory();
            //var builder = new ConfigurationBuilder()
            //   .SetBasePath(System.IO.Directory.GetCurrentDirectory())
            //   .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            //   .AddEnvironmentVariables();
            //_appConfiguration = builder.Build();
            _appConfiguration = env.GetAppConfiguration();
        }

        #region
        string GetTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}";
        /// <summary>
        /// 获取OpenId的微信连接
        /// </summary>
        string GetOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type={3}";
        //string GetTokenUrl = "";
        #endregion
        /// <summary>
        /// 获取凭证接口
        /// </summary>
        /// <param name="grant_type">获取access_token填写client_credential</param>
        /// <param name="appid">第三方用户唯一凭证</param>
        /// <param name="secret">第三方用户唯一凭证密钥，既appsecret</param>
        /// <returns></returns>
        [HttpGet]
        public AccessTokenResult GetToken(string appid, string secret, string grant_type = "client_credential")
        {
            //注意：此方法不能再使用ApiHandlerWapper.TryCommonApi()，否则会循环
            var url = string.Format(GetTokenUrl, grant_type, appid, secret);

            AccessTokenResult result = Get.GetJson<AccessTokenResult>(url);
            return result;
        }
        /// <summary>
        /// 获取OpenId
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpGet]
        [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
        public AjaxResult GetOpenId(string code)
        {
            var Result = new AjaxResult();
            try
            {
                var wechatConfig = GetWechatAppConfig();
                string url = string.Format(GetOpenIdUrl, wechatConfig.AppId, wechatConfig.AppSecret, code, "authorization_code");
                JsCode2JsonResult jsonResult = Get.GetJson<JsCode2JsonResult>(url);
                //Senparc.Weixin.HttpUtility.Get.
                //var jsonResult = SnsApi.JsCode2Json(wechatConfig.AppId, wechatConfig.AppSecret, code);//旧版本的senparc能够使用
                //string openId = jsonResult.openid;
                Result.Message = "请求成功";
                Result.IsSuccess = true;
                Result.IsException = false;
                Result.Data = jsonResult;
                
            }
            catch (Exception ex)
            {
                Result.IsSuccess = false;
                Result.IsException = true;
                Result.Message = ex.Message;
            }
            return Result;
        }
        /// <summary>
        /// 发起支付请求,生成暂存订单
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
        public async Task<AjaxResult> WechatPayOrder([FromBody]CreateActivityModel createActivityModel)
        {
            var Result = new AjaxResult();
            try
            {
                //if (string.IsNullOrWhiteSpace(createActivityModel.OpenId)) 
                //{
                //    throw new Exception("OpenId不能为空");
                //}
                var wechatConfig = GetWechatAppConfig();
                Logger.Error("WechatPayOrder", new Exception("config"));
                //判断登录用户是否是微信或官网用户
                var user = GetCurrentUser();
                if (StaticRoleNames.Host.Wechat != user.UserName && StaticRoleNames.Host.Web != user.UserName)
                {
                    throw new Exception("当前登录账户不能调用该方法");
                }
                //设置售票源为微信端
                var source = GetSourceList().FirstOrDefault(m=>m.SourceCode== user.UserName);
                createActivityModel.SourceId = source.Id;
                //设置支付方式为微信
                var payMethod = GetPayMethodList().FirstOrDefault(m => m.PayCode == "Wechat");
                createActivityModel.PayMethodId = payMethod.Id;
                //判断提交数据的正确性
                var activity = this.IsGetActivityTemp(createActivityModel);
                var activityTempDetail = activity.ActivityDetails.FirstOrDefault();
                var voucherNo = CommonHelp.getVoucherNo();
                activity.VoucherNo = voucherNo;//支付凭证号
                var jssdkUiPackage = JSSDKHelper.GetJsSdkUiPackage(wechatConfig.AppId, wechatConfig.AppSecret,"");
                var nonceStr = jssdkUiPackage.NonceStr;
                var timeStamp = jssdkUiPackage.Timestamp;
                var openid = activity.OpenId.IsNullOrWhiteSpace() ? "" : activity.OpenId;
                var tradeType = activity.OpenId.IsNullOrWhiteSpace() ? Senparc.Weixin.TenPay.TenPayV3Type.NATIVE : Senparc.Weixin.TenPay.TenPayV3Type.JSAPI;
                //向微信发送统一订单
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(
                    wechatConfig.AppId, GetConfig("XcxMchID") ,
                    activityTempDetail.Schedule.ScheduleCode + "--" + activityTempDetail.TicketPrice.TicketName,
                    voucherNo, Convert.ToInt32(activity.TotalAmount * 100), "8.8.8.8",
                    GetNotifyUrl(), tradeType, openid,
                    GetConfig("TenPayV3_Key"), nonceStr);
                Logger.Error("WechatPayOrder", new Exception(GetNotifyUrl()));
                var result = TenPayV3.Unifiedorder(xmlDataInfo);
                Logger.Error("WechatPayOrder", new Exception("result.ResultXml:" + result.ResultXml));

                if (result.result_code != "SUCCESS") throw new Exception("发送微信请求失败");
                //创建预留订单
                ActivityResultModel activityResultModel = await _activityTempManager.CreateActivity(activity);
                var package = string.Format("prepay_id={0}", result.prepay_id);

                var paySign = TenPayV3.GetJsPaySign(wechatConfig.AppId, timeStamp, nonceStr, package, GetConfig("TenPayV3_Key"));
                var vd = new TenPayV3Odrer()
                {
                    timestamp = timeStamp,
                    noncestr = nonceStr,
                    signtype = "MD5",
                    package = package,
                    paySign = paySign,
                    voucherNo = voucherNo,
                    code_url = result.code_url,
                };
                Result.Data = vd;
                return Result;
            }
            catch (Exception ex)
            {

                Result.IsSuccess = false;
                Result.IsException = true;
                Result.Message = ex.Message;
            }
            return Result;
        }
        /// <summary>
        /// 支付回调URL，对应于Service.Config.TenPayV3Notify
        /// </summary>
        /// <returns></returns>
        [HttpGet,HttpPost,HttpPut]
        public ActionResult PayNotifyUrl()
        {
            //Senparc.Weixin.WeixinTrace.SendCustomLog("支付回调URL", "进来了");
            Logger.Error("支付回调URL", new Exception("进来了"));
            try
            {
                this._httpContextAccessor.HttpContext.Request.EnableBuffering();
                Yozeev.Models.ResponseHandler resHandler = new Yozeev.Models.ResponseHandler(this._httpContextAccessor.HttpContext);

                string return_code = resHandler.GetParameter("return_code");
                string return_msg = resHandler.GetParameter("return_msg");
                //Senparc.Weixin.WeixinTrace.SendCustomLog("支付回调URL", resHandler.ParseXML());
                Logger.Error("支付回调URL", new Exception(resHandler.ParseXML()));
                string res = "wrong";

                resHandler.SetKey(GetConfig("TenPayV3_Key"));

                //验证请求是否从微信发过来（安全）!!!!!
                if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
                {
                    //校验商户Id--mch_id，小程序ID--appid，
                    var wechatConfig = GetWechatAppConfig();
                    if (resHandler.GetParameter("appid") == wechatConfig.AppId && resHandler.GetParameter("mch_id") == GetConfig("XcxMchID"))
                        res = "success";//正确的订单处理
                    //直到这里，才能认为交易真正成功了，可以进行数据库操作，但是别忘了返回规定格式的消息！

                }
                else
                {
                    res = "wrong";//错误的订单处理
                }

                Logger.Error("支付回调URL res=", new Exception(res));
                /* 这里可以进行订单处理的逻辑 */

                //TODO：判断订单状态（Lock）

                //发送支付成功的模板消息
                if (res == "success")
                {
                    try
                    {
                        //TODO：订单状态更新
                        //根据支付凭证号查找暂存订单
                        var voucherNo = resHandler.GetParameter("out_trade_no");
                        //Senparc.Weixin.WeixinTrace.SendCustomLog("支付回调URL提交暂存订单voucherNo", voucherNo);
                        Logger.Error("支付回调URL提交暂存订单voucherNo", new Exception(voucherNo));
                        var activityTemp = _activityTempManager.GetActivityTempByVoucherNo(voucherNo);
                        //填充订单信息
                        User user = _userManager.FindByNameAsync(StaticRoleNames.Host.Wechat).Result;
                        var activity = FillActivityByTemp(activityTemp, user);
                        //创建订单
                        ActivityResultModel activityResultModel = _activityManager.CreateActivity(activity, activityTemp);
                        //旅行社订单
                        if(activity.OrderType== OrderTypeEnum.OrderTypeTravelAgency)
                        {
                            TravelConsumerMessage travelMessage = new TravelConsumerMessage()
                            {
                                ActivityId = activityResultModel.ActivityId,
                                PayMethod = PayMethodEnum.PaySuccess,
                            };
                            _capBus.PublishAsync("swei.travel.activity.create", JsonConvert.SerializeObject(travelMessage));
                        }else
                        {
                            _capBus.PublishAsync("swei.activity.create", activityResultModel.ActivityId);
                        }
                        //Senparc.Weixin.WeixinTrace.SendCustomLog("支付回调URL提交暂存订单", "创建订单成功");
                        Logger.Error("支付回调URL提交暂存订单", new Exception("创建订单成功"));
                    }
                    catch (Exception ex)
                    {
                        //Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString());
                        //Senparc.Weixin.WeixinTrace.SendCustomLog("支付回调URL提交暂存订单voucherNo", "创建订单失败");
                        Logger.Error("支付回调URL 创建订单失败", ex);
                    }

                }

                #region 记录日志


                #endregion

                string xml = string.Format(@"<xml>
                <return_code><![CDATA[{0}]]></return_code>
                <return_msg><![CDATA[{1}]]></return_msg>
                </xml>", return_code, return_msg);
                Logger.Error("支付回调URL xml", new Exception(xml));
                return Content(xml, "text/xml");

            }
            catch (Exception ex)
            {
                Logger.Error("支付回调URL Exception", ex);
                //new WeixinException(ex.Message, ex);

                string xml = string.Format(@"<xml>
                <return_code><![CDATA[{0}]]></return_code>
                <return_msg><![CDATA[{1}]]></return_msg>
                </xml>", "FAIL", ex.Message);
                return Content(xml, "text/xml");
            }
        }
        /// <summary>
        /// 重新支付暂存订单
        /// </summary>
        /// <param name="ActivityTempId">暂存订单Id</param>
        /// <returns></returns>
        [HttpPost]
        [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
        public async Task<AjaxResult> WechatPayOrderAgain(Guid ActivityTempId)
        {
            var Result = new AjaxResult();
            try
            {
                //查询暂存订单
                var activityTemp = _activityTempManager.GetActivityTempById(ActivityTempId);
                var wechatConfig = GetWechatAppConfig();
                Logger.Error("WechatPayOrder", new Exception("config"));
                //判断登录用户是否是微信用户
                if (StaticRoleNames.Host.Wechat != GetCurrentUser().UserName)
                {
                    throw new Exception("当前登录账户不是微信用户");
                }
                CreateActivityModel createActivityModel = new CreateActivityModel()
                {
                    SourceId = GetSourceList().FirstOrDefault(m => m.SourceCode == "WeChat").Id,
                    PayMethodId = GetPayMethodList().FirstOrDefault(m => m.PayCode == "Wechat").Id,
                    OrderType = OrderTypeEnum.OrderTypeCustomer,
                    Remark = "WechatOrderAgain",
                    OpenId = activityTemp.OpenId,
                    activityDetails = new List<CreateActivityDetailModel>(),
                };
                activityTemp.ActivityDetails.ToList().ForEach(atd => {
                    CreateActivityDetailModel createActivityDetailModel = new CreateActivityDetailModel()
                    {
                        quantity = 1,
                        ticketPriceId = atd.TicketPriceId,
                        ScheduleId = (Guid)atd.ScheduleId,
                        customerId = atd.CustomerId,
                    };
                    createActivityModel.activityDetails.Add(createActivityDetailModel);
                });
                //判断是否可售票的正确性
                var activity = this.IsGetActivityTemp(createActivityModel);

                var activityTempDetail = activity.ActivityDetails.FirstOrDefault();
                var voucherNo = CommonHelp.getVoucherNo();
                activityTemp.VoucherNo = voucherNo;//支付凭证号
                var jssdkUiPackage = JSSDKHelper.GetJsSdkUiPackage(wechatConfig.AppId, wechatConfig.AppSecret, "");
                var nonceStr = jssdkUiPackage.NonceStr;
                var timeStamp = jssdkUiPackage.Timestamp;
                //向微信发送统一订单
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(
                    wechatConfig.AppId, GetConfig("XcxMchID"),
                    activityTempDetail.Schedule.ScheduleCode + "--" + activityTempDetail.TicketPrice.TicketName,
                    voucherNo, Convert.ToInt32(activity.TotalAmount * 100), "8.8.8.8",
                    GetNotifyUrl(), Senparc.Weixin.TenPay.TenPayV3Type.JSAPI, activity.OpenId,
                    GetConfig("TenPayV3_Key"), nonceStr);
                Logger.Error("WechatPayOrder", new Exception(GetNotifyUrl()));
                var result = TenPayV3.Unifiedorder(xmlDataInfo);
                Logger.Error("WechatPayOrder", new Exception("result.ResultXml:" + result.ResultXml));
                if (result.result_code != "SUCCESS") throw new Exception("发送微信请求失败");
                //修改预留订单凭证号
                await _activityTempManager.UpdateActivityTemp(ActivityTempId, voucherNo);
                //ActivityResultModel activityResultModel = await _activityTempManager.CreateActivity(activity);
                var package = string.Format("prepay_id={0}", result.prepay_id);

                var paySign = TenPayV3.GetJsPaySign(wechatConfig.AppId, timeStamp, nonceStr, package, GetConfig("TenPayV3_Key"));
                var vd = new TenPayV3Odrer()
                {
                    timestamp = timeStamp,
                    noncestr = nonceStr,
                    signtype = "MD5",
                    package = package,
                    paySign = paySign,
                };
                Result.Data = vd;
                return Result;
            }
            catch (Exception ex)
            {

                Result.IsSuccess = false;
                Result.IsException = true;
                Result.Message = ex.Message;
            }
            return Result;
        }


        /// <summary>
        /// 根据票据Id退票，暂存订单支付状态不变，只修改票据状态，可以调用/api/services/app/ActivityTempDetail/GetDetailListByTempId查询状态
        /// </summary>
        /// <param name="TicketDetailId">票据id</param>
        /// <returns></returns>
        [HttpGet,HttpPost]
        public AjaxResult Refund(Guid TicketDetailId)
        {
            var Result = new AjaxResult();
            try
            {
                decimal rDiscount = 1;
                var wechatConfig = GetWechatAppConfig();
                //查找对应票据
                var ticketDetails = _ticketDetailManager.GetTicketDetailList(new List<Guid>() { TicketDetailId });
                //查找暂存订单
                var activityTemp = _activityTempManager.GetActivityTempByActivityId(ticketDetails.FirstOrDefault().ActivityId);
                //检验退票信息
                var ticketDetailList = CheckRefundList(ticketDetails);

                string nonceStr = TenPayV3Util.GetNoncestr();
                string outTradeNo = activityTemp.VoucherNo;
                string outRefundNo = "OutRefunNo-" + DateTime.Now.Ticks;
                int totalFee = Convert.ToInt32(ticketDetails.Sum(m => m.ActivityDetail.SalePrice * rDiscount) * 100);//该票金额，全额退款
                int refundFee = totalFee;
                string opUserId = GetConfig("XcxMchID");
                var dataInfo = new TenPayV3RefundRequestData(wechatConfig.AppId, GetConfig("XcxMchID"), GetConfig("TenPayV3_Key"),
                    null, nonceStr, null, outTradeNo, outRefundNo, totalFee, refundFee, opUserId, null);
                var cert = GetConfig("Cert");//根据自己的证书位置修改
                var password = GetConfig("Password");//默认为商户号，建议修改
                var result = TenPayV3.Refund(dataInfo, cert, password);
                Logger.Error("微信小程序Refund", new Exception(result.ResultXml));
                //退款成功
                if(result.result_code == "SUCCESS")
                {
                    Result.IsSuccess = result.result_code == "SUCCESS"; 
                    var resultModel = _activityManager.RefundActivity(ticketDetailList, (long)AbpSession.UserId, rDiscount, "sweiiWechat");
                    //修改暂存订单状态
                    //activityTemp.
                    Logger.Error("微信小程序Refund 退款成功", new Exception(""));
                }
            }
            catch (Exception ex)
            {
                Logger.Error("微信小程序Refund 退款失败", ex);
                Result.IsSuccess = false;
                Result.IsException = true;
                Result.Message = ex.Message;

            }
            return Result;
        }

        #region 被扫支付 ==============================
        /// <summary>
        /// 被扫支付
        /// </summary>
        /// <param name="model">提交订单信息实体</param>
        /// <returns></returns>
        [HttpGet, HttpPost]
        public async Task<AjaxResult> WeiXinRunPay(TicketActivityModel model)
        {
            var Result = new AjaxResult();
            try
            {
                this._httpContextAccessor.HttpContext.Request.EnableBuffering();
                Yozeev.Models.ResponseHandler resHandler = new Yozeev.Models.ResponseHandler(this._httpContextAccessor.HttpContext);

                Logger.Error("开始执行下单操作");
                Logger.Error("收到的实体内容：付款码："+model.auth_code+">>>金额："+model.total_fee.ToString());
                //添加临时订单
                #region 添加临时订单
                var wechatConfig = GetWechatAppConfig();
                Logger.Error("WeiXinRunPay", new Exception("config"));

                //判断登录用户是否是微信或官网用户
                if (StaticRoleNames.Host.Zizhuji != GetCurrentUser().UserName )
                {
                    throw new Exception("当前登录账户不能调用该方法");
                }

                //创建临时订单
                CreateActivityModel createActivityModel = new CreateActivityModel()
                {
                    SourceId = GetSourceList().FirstOrDefault(m => m.SourceCode == "TicketMachine").Id,
                    PayMethodId = GetPayMethodList().FirstOrDefault(m => m.PayCode == "Wechat").Id,
                    VoucherNo= CommonHelp.getVoucherNo(),
                    OrderType = OrderTypeEnum.OrderTypeCustomer,
                    CreateUserId=Convert.ToInt64(model.userID),
                    TotalQuantity= Convert.ToInt32(model.total_quantity),
                    TotalAmount= Convert.ToDecimal(model.total_fee),
                    Remark = "ZiZhuJi",
                    OpenId = "",
                    activityDetails = new List<CreateActivityDetailModel>(),
                };

                //判断提交数据的正确性
                var activity = this.IsGetActivityTemp(createActivityModel);

                var activityTempDetail = activity.ActivityDetails.FirstOrDefault();
                var voucherNo = CommonHelp.getVoucherNo();
                activity.VoucherNo = voucherNo;//支付凭证号
                var jssdkUiPackage = JSSDKHelper.GetJsSdkUiPackage(wechatConfig.AppId, wechatConfig.AppSecret, "");
                var nonceStr = jssdkUiPackage.NonceStr;
                var timeStamp = jssdkUiPackage.Timestamp;
                var openid = activity.OpenId.IsNullOrWhiteSpace() ? "" : activity.OpenId;
                var tradeType = activity.OpenId.IsNullOrWhiteSpace() ? Senparc.Weixin.TenPay.TenPayV3Type.NATIVE : Senparc.Weixin.TenPay.TenPayV3Type.JSAPI;

                //创建预留订单
                ActivityResultModel activityResultModel = await _activityTempManager.CreateActivity(activity);

                //向微信发送统一订单
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(
                    wechatConfig.AppId, GetConfig("XcxMchID"),
                    activityTempDetail.Schedule.ScheduleCode + "--" + activityTempDetail.TicketPrice.TicketName,
                    voucherNo, Convert.ToInt32(activity.TotalAmount * 100), "8.8.8.8",
                    GetNotifyUrl(), tradeType, openid,
                    GetConfig("TenPayV3_Key"), nonceStr);
                Logger.Error("WeiXinRunPay", new Exception(GetNotifyUrl()));
                var result = TenPayV3.Unifiedorder(xmlDataInfo);
                Logger.Error("WeiXinRunPay", new Exception("result.ResultXml:" + result.ResultXml));

                //等待微信返回数据验证
                bool flag = false;
                //如果提交被扫支付接口调用失败，则抛异常
                if (result.result_code == "SUCCESS"&&result.return_code== "SUCCESS") 
                {
                    flag = true;
                }
                else
                {
                    //确认支付是否成功,每隔一段时间查询一次订单，共查询10次
                    int queryTimes = 30;//查询次数计数器
                    while (queryTimes-- > 0)
                    {
                        int succResult = 0;//查询结果
                        //查询订单是否有回调处理生成正式订单
                        var activityOrder = _activityManager.GetActivityByVoucherNo(createActivityModel.VoucherNo);
                        if (activityOrder != null)
                        {
                            //直接返回订单信息
                            var tickets = _ticketDetailManager.GeTicketDetailByActivityId(activityOrder.Id.ToString());
                            Result.IsSuccess = true;
                            Result.Message = "下单成功";
                            Result.Data = tickets;

                            return Result;
                        }
                        else
                        {
                            Thread.Sleep(2000);
                            continue;
                        }
                    }
                 }
            
                    #endregion

            }
            catch (Exception ex)
            {
                Result.Message = "错误：" + ex.Message.ToString();
                return Result;
            }

            return Result;
        }

        #endregion

        #region 私有方法
        /// <summary>
        /// 获取微信小程序的配置信息
        /// </summary>
        /// <returns></returns>
        WechatAppConfig GetWechatAppConfig()
        {
            WechatAppConfig wechatAppConfig = new WechatAppConfig();
            //从缓存中获取
            var cacheKey = CacheConsts.HostApi;
            //if (AbpSession.TenantId.HasValue)
            //{
            //    cacheKey = $"{AbpSession.TenantId}-{CacheConsts.HostApi_TokenAuth_Authenticate}";
            //}
            var cache = _cacheManager.GetCache(cacheKey);
            wechatAppConfig = cache.GetOrDefault<string, WechatAppConfig>("WechatAppConfig");
            if (wechatAppConfig == null || wechatAppConfig.Id == 0)
            {
                //查询微信配置表获取_appid，_appSecret
                var query = _wechatAppConfigManager.Query("",false).Result.ToList();
                if (query.Count() > 0)
                {
                    wechatAppConfig = query.FirstOrDefault();
                    //保存到缓存中
                    cache.SetAsync("WechatAppConfig", wechatAppConfig);
                }
                else
                {
                    //获取配置文件中的wechatAppConfig
                    wechatAppConfig = new WechatAppConfig();
                    wechatAppConfig.AppId = _appConfiguration["Authentication:Wechat:AppId"];
                    wechatAppConfig.AppSecret = _appConfiguration["Authentication:Wechat:AppSecret"];
                }
            }
            return wechatAppConfig;
        }
        /// <summary>
        /// 生成回调地址
        /// </summary>
        /// <returns></returns>
        string GetNotifyUrl()
        {
            //return "http://zc.device.sweii.cn/CheckTicket/CardOpen";
            return new StringBuilder()
                .Append(Request.Scheme)
                .Append("://")
                .Append(Request.Host)
                .Append(Request.PathBase)
                .Append("/api/WechatPay/PayNotifyUrl")
                .ToString();
        }

        string GetConfig(string str)
        {
            return _appConfiguration["Authentication:Wechat:" + str];

        }

        #region 查询订单
        /// <summary>
        /// 订单查询
        /// </summary>
        /// <returns></returns>
        JsonResult OrderQuery(String out_trade_no, out int succCode)
        {
            string nonceStr = TenPayV3Util.GetNoncestr();

            RequestHandler packageReqHandler = new RequestHandler(null);

            //设置package订单参数
            packageReqHandler.SetParameter("appid", GetWechatAppConfig().AppId);          //公众账号ID
            packageReqHandler.SetParameter("mch_id", GetConfig("XcxMchID"));          //商户号
            //packageReqHandler.SetParameter("transaction_id", "");       //填入微信订单号 
            packageReqHandler.SetParameter("out_trade_no", out_trade_no);         //填入商家订单号
            packageReqHandler.SetParameter("nonce_str", nonceStr);             //随机字符串

            string querysign = packageReqHandler.CreateMd5Sign("key", GetConfig("TenPayV3_Key"));

            packageReqHandler.SetParameter("sign", querysign);                        //签名

            string data = packageReqHandler.ParseXML();

            var result = TenPayV3.OrderQuery(data);
            var res = System.Xml.Linq.XDocument.Parse(result);

            string return_code = res.Element("xml").Element("return_code").Value;
            string trade_state = res.Element("xml").Element("trade_state").Value;//SUCCESS-支付成功，REFUND-转入退款,NOTPAY-未支付,CLOSED-已关闭，REVOKED-已撤销,USERPAYING-用户支付中，PAYERROR-支付失败
            string err_code= res.Element("xml").Element("err_code").Value;

            if (return_code == "SUCCESS")
            {
                //支付成功
                if (trade_state == "SUCCESS")
                {
                    succCode = 1;
                    return Json(result); 
                }
                else if (trade_state == "USERPAYING")
                {
                    succCode = 2;
                    return Json(result); 
                }
                else if (trade_state == "PAYERROR")
                {
                    succCode = 3;
                    return Json(result);;
                }
            }

            if (err_code == "ORDERNOTEXIST")
            {
                succCode = 0;
            }
            else
            {
                succCode = 2;
            }


            Hashtable hashtable = new Hashtable();

            hashtable.Add("trade_state", trade_state);

            return Json(result);
        }
        #endregion


        #endregion
    }
}
